#include "FindFileSizes.h"
#include <boost/filesystem/operations.hpp>
#include "boost/filesystem.hpp"
#include <QtGui>
#include "mainwindow.h"

void FindFileSizes::initializeVariables(QStringList backupList, QString backupPath) {
    this->backupList = backupList;
    this->backupPath = backupPath;
}

void FindFileSizes::run()
{   
    // finds the number of files to be backed up for the progress bar
    tally = tallyFiles();

    // Start by filling sumFileSizes with the size of things to be backed up
    findBackupSize();

    // "backupDrive" is used to store the destination backup drive
    QString backupDrive = backupPath.left(3);

    // finds the free space on destination drive
    freeSpace = boost::filesystem::space(backupDrive.toStdString()).free;

    // Send 'em back to mainwindow.cpp
    emit sendFileSizes(sumFileSizes, freeSpace);
}

unsigned long int FindFileSizes::tallyFiles()
{
    // used for updating the progress bar
    unsigned long int numFiles = 0;

    // run through everything in the backup list to count the files
    for (int i = 0; i < backupList.count(); i++) {
        QString listItemText = backupList.at(i);

        // if a directory was found, find the number of files in it
        if( MainWindow::isDirectory(listItemText) ) {
            numFiles += numFilesInFolder(listItemText);
        }
        // otherwise it was a file, so increment the file count
        else {
            numFiles += 1;
        }
    }
    return numFiles;
}

unsigned long int FindFileSizes::numFilesInFolder(QString folder)
{
    QDir dir(folder);
    unsigned long int numFiles = 0;
    QStringList fileEntries = dir.entryList(QDir::Files | QDir::Hidden);

    // counts all of the files in the directory
    numFiles += fileEntries.count();

    // uses recursion to find out the number of files in each directory
    QStringList dirEntries = dir.entryList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Hidden);
    foreach(QString dirEntry, dirEntries) {
        numFiles += numFilesInFolder(folder + "/" + dirEntry);
    }

    return numFiles;
}

void FindFileSizes::findBackupSize()
{
    // initializes at 0 for each time the files are backed up
    sumFileSizes = 0;

    // used for the progress bar
    // progress update is used to tell the progress bar how many files need to be processed before updating
    numProcessed = 0;
    progressUpdate = 0;

    // we didn't #include the max thing so we are using this
    if ((int)(tally / 100) >= 1) {
        progressUpdate = (int)(tally / 100);
    }
    else {
        progressUpdate = 1;
    }

    // runs through all of the user's paths
    for ( int i = 0; i < backupList.count(); i++ ) {

        // each iteration grabs a new path
        QString listItemText = backupList.at(i);
        if( MainWindow::isDirectory(listItemText) ) {

            QDir temp(listItemText);
            temp.cdUp();

            sumFileSizes += findFolderSize(temp.path(), listItemText);

        }
        else {
            sumFileSizes += findFileSize(listItemText, backupPath + MainWindow::onlyFileName(listItemText));
            numProcessed++;

            // checks to see if the progress bar needs to be updated after a file size was found
            checkForProgressUpdate();
        }
    }
}

qint64 FindFileSizes::findFolderSize(QString source, QString myFolder)
{
    if ( !myFolder.endsWith("/") ) {
        myFolder.append("/");
    }

    if ( !source.endsWith("/") ) {
        source.append("/");
    }

    // See comments in "copyFolder" for why this is being done
    QString endOfPath(myFolder);
    endOfPath.replace(source, "");
    QDir backupDir(backupPath + endOfPath);

    QDir dir(myFolder);
    qint64 folderSize = 0;

    // Find the sum of the file sizes
    QStringList fileEntries = dir.entryList(QDir::Files | QDir::Hidden);
    foreach(QString fileEntry, fileEntries) {
        folderSize += findFileSize(myFolder + fileEntry, backupDir.path() + "/" + fileEntry);
        numProcessed++;

        // checks to see if the progress bar needs to be updated after a file size was found
        checkForProgressUpdate();
    }

    // Find sum of the folder sizes (recursive)
    QStringList dirEntries = dir.entryList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Hidden);
    foreach(QString dirEntry, dirEntries) {
        folderSize += findFolderSize(source, myFolder + dirEntry);
    }

    return folderSize;
}

qint64 FindFileSizes::findFileSize(QString myFile, QString pathOnBackup)
{
    // makes sure the file exists
    if (QFile::exists(myFile)) {

        QFile file(myFile);
        // Only keep track of the sizes of the files that have been changed (i.e. newer lastModified date) or don't
        // exist in the destination folder.
        if (!QFile::exists(pathOnBackup) || MainWindow::fileLastModified(myFile) > MainWindow::fileLastModified(pathOnBackup)) {
            //addToConsole(myFile + " has file size: " + QString::number(file.size()));
            return file.size();
        }

    }
    return 0;
}

void FindFileSizes::checkForProgressUpdate()
{
    // numProcessed holds the number of files that had their sizes checked
    // progressUpdate contains a number, and this number tells how many files have to be processed
    // for each update
    if(numProcessed % progressUpdate == 0) {
        percent = (int)ceil(((double)numProcessed / tally) * 100);
        emit sendFileSizePercentage(percent);
    }
}
